// 用对象作为单例或存放工具方法
// 类可以拥有一个同名的伴生对象
// 对象可以扩展类或特质
// 对象的apply方法通常用来构造伴生类的新实例
// 如果不想显式定义main方法，可以用扩展App特质的对象
// 可以通过扩展Enumeration对象来实现枚举

// 单例对象
// scala没有静态方法或静态字段（重要！），可以用object这个语法结构来达到同样目的。
// 对象定义了某个类的单个实例，包含了想要的特性。
object Acc {
private var lastNumber = 0
def newUniqueNumber() = {lastNumber += 1; lastNumber}
}
// 你不能new一个object
// 对象的构造器在该对象第一次被使用时才调用
// 对象本质上可以拥有类的所有特性，甚至可以扩展其他类或特质，不能提供构造器参数
// 对象的使用特点：
//	作为存放工具函数或常量的地方
//	高效地共享单个不可变实例
//	需要用单个实例来协调某个服务时（单例模式）

// 6.2 伴生对象
// 如果你希望一个类中有实例方法又有静态方法，可以用伴生对象实现。
// 类和它的伴生对象可以相互访问私有参数和方法
// 类和它的伴生对象必须存在于同一个源文件中

// 6.3 扩展类或特质的对象
// 一个对象可以扩展类以及一个或多个特质

// 6.4 apply方法
// 对象名() 是 对象名.apply的简写
// Array(100)是新建一个Array，只有一个元素：100；new Array(100),新建一个Array[Nothing],有100个元素
class Acc(id:Int,name:String,bal:Double) { // 这个很重要哦
println("id:"+id+" ,name:"+name+" ,bal:"+bal)
}
object Acc {
def apply(id:Int,name:String,bal:Double) = {
new Acc(id,name,bal)
}
}


// 6.5 应用程序对象
object Hello {
def main(args:Array[String]) {
println("hello world")
}
}
// 继承App特质，就可以将程序代码直接放入构造器方法体内：
object Hello extends App {
println("hello")
}
// 虽然不能直接看到args，但可以调用：
object Hello extends App {
if (args.length>0)
	println("hello " + args(0))
else
	println("hello")
}

// 枚举
// scala没有枚举类型，但可以扩展Enumeration类来产生枚举
object enum1 extends Enumeration {
val red,yellow,green = Value
}

// 上面的代码定义了三个字段，然后调用Value这个内部类来初始化它们
// Value有两个参数，ID和名称，如果不传ID，在前一个参数的ID上增加1，如果不传名称，默认为字段名。

object enum1 extends Enumeration {
val red = Value(100, "Stop")
val yellow = Value
val green = Value("GO")
}

// 上面的yellow ID为101，名称为yellow；green ID为102，名称为GO


object charpter06 extends App {
  /*
   * 6.1
   *  编写一个Conversions对象, 
   *  加入inchesToCentimeters  gallonsToLiters和milesToKilometers方法
   */
object Conversions {
def inchesToCentimeters(x:Double) = {
x*2.54
}
def gallonsToLiters(x:Double) = {
x*3.78541178
}
def milesToKilometers(x:Double) = {
x*0.6213712
}
}

def question1(): Unit = {
    object Conversations {
      def inches2Centimeters(inch: Double): Double = {
        2.54 * inch
      }
      def gallons2Liters(gallon: Double): Double = {
        3.78541178 * gallon
      }
      def miles2Kilometers(mile: Double): Double = {
        0.6213712 * mile
      }
    }
  }

  /*
   * 6.2
   * 前一个联系不是很面向对象, 
   * 提供一个通用的超类UnitConversion并定义扩展该超类的InchesToCentimeters
   *   GallonsToLiters和MilesToKilometers对象
   */
  def question2(): Unit = {
    abstract class UnitConversion {
      def inchesToCentimeters() {}
      def gallonsToLiters() {}
      def milesToKilometers() {}
    }
    object InchesToCentimeters extends UnitConversion {
      override def inchesToCentimeters() {}
    }
    object GallonsToLiters extends UnitConversion {
      override def gallonsToLiters() {}
    }
    object MilesToKilometers extends UnitConversion {
      override def milesToKilometers() {}
    }
  }

  /*
   * 6.3
   * 定义一个扩展自java.awt.Point的Origin对象, 为什么说这实际上不是个好主意?
   */
  def question3(): Unit = {
    class Origin extends java.awt.Point {}
  }

  /*
   * 6.4
   * 定义一个Point类和一个伴生对象, 
   * 使得我们可以不用new而直接用Point(3,4)来构造Point实例
   */
class Point(x:Int,y:Int) {}
object Point {
def apply(x:Int,y:Int)={
new Point(x,y)
}
}
  
  
  def question4(): Unit = {
    class Point(val x: Int, val y: Int) {}
    object Point {
      def apply(x: Int, y: Int): Point = {
        new Point(x, y)
      }
    }
  }

  /*
   * 6.5
   * 编写一个Scala应用程序, 使用App特质, 以反序打印命令行参数, 用空格隔开,
   * 举例来说, scala Reverse Hello World应该打印出World Hello
   */
object q5 App {
for (i<- args reverse) println(i+" ")
}



  def question5(): Unit = {
    args.reverse foreach { x => print(x + " ") }
  }

  /*
   * 6.6
   * 编写一个扑克牌4种花色的枚举, 使其toString方法分别返回 ♣ ♠ ♥ ♦
   */
  def question6(): Unit = {
    object Joker extends Enumeration {
      val M: Value = Value("♣")
      val T: Value = Value("♠")
      val H: Value = Value("♥")
      val F: Value = Value("♦")
      def color(c: Joker.Value) {
        if (c == Joker.M || c == Joker.T) print("Black")
        else print("Red")
      }
    }

    Joker.getClass.getFields foreach { x => println(x.get(null).toString + " ") }
  }

  /*
   * 6.7
   * 实现一个函数, 检查某张牌的花色是否为红色
   */
  def question7(): Unit = question6()

  /*
   * 6.8
   * 编写一个枚举,描述RGB立方体的八个角, ID使用颜色值 (例如, 红色是0xff0000)
   */
  def question8(): Unit = {
    class RGB extends Enumeration {
      val RED: Value = Value(0xff0000, "Red")
      val BLACK: Value = Value(0x000000, "Black")
      val GREEN: Value = Value(0x00ff00, "Green")
      val CYAN: Value = Value(0x00ffff, "Cyan")
      val YELLOW: Value = Value(0xffff00, "Yellow")
      val WHITE: Value = Value(0xffffff, "White")
      val BLUE: Value = Value(0x0000ff, "Blue")
      val MAGENTA: Value = Value(0xff00ff, "Magenta")
    }
  }

  question6()
}